import React from "react";
import useStyles from "./styles";
import { Delete as DeleteIcon } from "@ct0/icons";
import dayjs from "dayjs";
import classNames from "classnames";
import type {
  ConditionItemProps,
  ConditionsProps,
  RevealFieldBase,
} from "./type";
import type { NestFilterConditions, NestFilterOperator } from "../type";
import { OPERATOR_NAMES } from "../utils";

export default Conditions;

function getKeyLabel(fields: Array<RevealFieldBase>, key: string) {
  for (let field of fields) if (field.key == key) return field.label;
  return key;
}

function getOperatorLabel(operator: NestFilterOperator) {
  return OPERATOR_NAMES[operator] || operator;
}

function formatDate(
  v: string | number,
  format: string = "YYYY-MM-DD HH:mm:ss"
) {
  return dayjs(v).format(format);
}

function getValueLabel({
  key,
  operator,
  fields,
  value,
}: {
  fields: Array<RevealFieldBase>;
  operator: string;
  key: string;
  value: Array<string | number | boolean | undefined>;
}) {
  let field: RevealFieldBase | undefined;

  for (let i of fields) if (i.key == key) field = i;
  if (!field) return `条件筛选 key 异常: ${key}`;

  if (operator == "is null") return value[0] ? "是" : "否";

  if (field.javascriptType.isBoolean) return value[0] ? "是" : "否";

  if (field.javascriptType.isTimestamp) {
    if (operator == "between") {
      return `${formatDate(value[0] as string)} ~ ${formatDate(
        value[1] as string
      )}`;
    }
    return formatDate(value[0] as string);
  }

  if (field.javascriptType.isDate) {
    if (operator == "between") {
      return `${formatDate(value[0] as string, "YYYY-MM-DD")} ~ ${formatDate(
        value[1] as string,
        "YYYY-MM-DD"
      )}`;
    }
    return formatDate(value[0] as string, "YYYY-MM-DD");
  }

  if (field.options && typeof field.options != "function") {
    const labels = [];
    for (let option of field.options) {
      for (const i of value) {
        if (option.value == i) labels.push(option.label);
      }
    }
    return labels.join(", ");
  }

  return String(value);
}

function Conditions({
  conditions,
  fields,
  tailSlot,
  onChange,
}: ConditionsProps<RevealFieldBase>) {
  const classes = useStyles();

  const remove = (n: number) => {
    if (!conditions) return;
    onChange?.([...conditions.slice(0, n), ...conditions.slice(n + 1)]);
  };

  const change = (n: number, v: NestFilterConditions) => {
    if (!conditions) return;
    const node = conditions[n];
    if ("conditions" in node) {
      node.conditions = v;
      // 如果 v 已经是空数组，那么就直接删除这个节点
      const conds =
        v.length == 0
          ? [...conditions.slice(0, n), ...conditions.slice(n + 1)]
          : [...conditions];
      onChange?.(conds);
    }
  };

  return (
    <div className={classes.conditionPanel}>
      {conditions?.map((i, index) => {
        if ("conditions" in i) {
          return (
            <React.Fragment key={index}>
              {index != 0 && (
                <span className={classes.itemJoint}>{i.joint}</span>
              )}
              <span className={classes.brackets}>(</span>
              <Conditions
                fields={fields}
                conditions={i.conditions}
                onChange={(v) => change(index, v)}
              />
              <span className={classes.brackets}>)</span>
            </React.Fragment>
          );
        } else {
          const cond = i.condition;
          return (
            <Item
              key={index}
              isFirst={index == 0}
              joint={i.joint}
              fieldKey={getKeyLabel(fields, cond.key)}
              oper={getOperatorLabel(cond.operator)}
              value={getValueLabel({
                fields,
                key: cond.key,
                value: cond.value,
                operator: cond.operator,
              })}
              onClose={() => remove(index)}
            />
          );
        }
      })}
      {tailSlot && <div className={classes.tailSlot}>{tailSlot}</div>}
    </div>
  );
}

function Item({
  isFirst,
  fieldKey,
  joint,
  oper,
  value,
  onClose,
}: ConditionItemProps) {
  const classes = useStyles();

  const text = Array.isArray(value)
    ? value.map((i) => String(i)).join("、")
    : String(value);

  return (
    <div className={classes.item}>
      {!isFirst && <span className={classes.itemJoint}>{joint}</span>}
      <span className={classes.singleClause}>
        <span>{fieldKey}</span>
        <span className={classes.singleClauseOper}>{oper}</span>
        <span
          title={text}
          className={classNames(classes.singleClauseValue, classes.ellipsis)}
        >
          {text}
        </span>
        <span className={classes.singleClauseClose} onClick={onClose}>
          <DeleteIcon />
        </span>
      </span>
    </div>
  );
}
